<template>
  <div class="flex overflow-hidden h-full flex-col bg-#f7f9fc z-20 app-crud">
    <AppCard v-if="$slots.default || $slots.action" :border="false">
      <div class="flex justify-between" style="">
        <div class="flex-1 flex pb-12 pt-12 px-10">
          <div class="flex-1 flex">
            <slot></slot>
          </div>
          <div class="flex-shrink-0">
            <el-space>
              <!--              <el-tooltip placement="bottom" content="查询">-->
              <!--                <el-button circle @click="handleQuery" attr-type="submit">-->
              <!--                  <template #icon>-->
              <!--                    <el-icon>-->
              <!--                      <Search></Search>-->
              <!--                    </el-icon>-->
              <!--                  </template>-->
              <!--                </el-button>-->
              <!--              </el-tooltip>-->
              <el-tooltip
                placement="bottom"
                content="刷新"
                v-if="$slots.default"
              >
                <el-button circle @click="handleReset">
                  <template #icon>
                    <Refresh></Refresh>
                  </template>
                </el-button>
              </el-tooltip>
              <slot name="action"></slot>
            </el-space>
          </div>
        </div>
      </div>
    </AppCard>

    <AppCard class="flex-1 overflow-hidden" :border="false">
      <template #default="{ height }">
        <div class="flex wh-full overflow-hidden">
          <slot name="left" v-if="$slots.left"></slot>
          <div class="flex-1 flex-col flex" w-full>
            <div class="flex-1 overflow-hidden px-10" ref="tableWrap">
              <el-table
                :data="tableData"
                v-loading="loading"
                column-resizable
                :height="height"
                border
                v-if="isTable"
                @change="onSortChange"
              >
                <template v-for="column in columns">
                  <el-table-column
                    :label="column.title"
                    :prop="column.dataIndex"
                    :align="column.align"
                    :width="column.width"
                  >
                    <!-- 如果有 render，就自定义渲染 -->
                    <template #default="scope" v-if="column.render">
                      <component :is="column.render(scope)" />
                    </template>
                  </el-table-column>
                </template>
              </el-table>
              <slot
                name="data"
                :loading="loading"
                :record="tableData"
                :height="height"
                v-else
              ></slot>
            </div>
          </div>
        </div>
      </template>
    </AppCard>

    <AppCard :border="false" v-if="isPagination">
      <div class="h-50 flex items-center justify-end px-20">
        <el-pagination
          v-model:current-page="pagination.current"
          :page-size="pageSize"
          :total="pagination.total"
          @current-change="onPageChange"
          @size-change="onSizeChange"
          background
        ></el-pagination>
      </div>
    </AppCard>
    <div class="h-12" v-else></div>
  </div>
</template>

<script setup lang="ts">
import AppCard from "./app-card.vue";
import useLoading from "@/hooks/loading";
import { PageQueryDto } from "@/api/types";
import utils from "xe-utils";
import { Refresh, Search } from "@element-plus/icons-vue";

const props = defineProps({
  query: {
    type: Object,
    default() {
      return {};
    },
  },
  getData: {
    type: Function,
    required: false,
  },
  isPagination: {
    type: Boolean,
    default: true,
  },
  pageSize: {
    type: Number,
    default: 10,
  },
  remote: {
    type: Boolean,
    default: true,
  },
  columns: {
    type: Array,
    required: false,
  },
  defaultSort: {
    type: String,
    default: "weight",
  },
  isTable: {
    type: Boolean,
    default: true,
  },
});

const tableWrap = ref();
const tableHeight = ref("0px");

const emits = defineEmits([
  "onDataChange",
  "update:query",
  "onSortChange",
  "onReset",
  "onQuery",
]);
const { loading, setLoading } = useLoading();

const pagination = reactive({
  current: 1,
  pageSize: props.pageSize,
  total: 0,
  showTotal: true,
  showPageSize: true,
});
const tableData = ref([]);
const initQuery = { ...props.query };

function init() {
  tableHeight.value = tableWrap.value?.offsetHeight || 0 + "px";
}

const myQuery = onQueryChange();

watch(
  () => props.query,
  () => {
    myQuery();
  },
  {
    deep: true,
  },
);

function onQueryChange() {
  return utils.debounce(() => {
    handleQuery();
  }, 1000);
}

window.onresize = () => init();

async function handleQuery(loading?: boolean) {
  emits("onQuery");
  try {
    setLoading(loading === undefined ? true : loading);
    let paginationParams: PageQueryDto<typeof props.query> = {
      page: 1,
      size: 10,
      sort: props.defaultSort,
      order: "desc",
    };
    if (props.isPagination && props.remote) {
      paginationParams.page = pagination.current;
      paginationParams.size = pagination.pageSize;
      paginationParams.model = { ...props.query };

      const { data } = await props.getData(paginationParams);
      tableData.value = data.record.map((item: any, index: number) => {
        const { page, size } = paginationParams;
        return {
          ...item,
          dataIndex: (page - 1) * size + index + 1,
        };
      });
      pagination.total = data.total;
    } else {
      const { data } = await props.getData(props.query);
      tableData.value = data.record || data || [];
    }
  } catch (error) {
    tableData.value = [];
    pagination.total = 0;
  } finally {
    emits("onDataChange", tableData.value);
    setLoading(false);
  }
}

async function handleReset() {
  emits("onReset");
  setLoading(true);
  // const queryItems = { ...props.query }
  // for (const queryItemsKey in queryItems) {
  //   queryItems[queryItemsKey] = null
  // }
  //
  // emits('update:query', { ...queryItems, ...initQuery })
  // await nextTick()
  // pagination.current = 1
  setTimeout(() => {
    handleQuery(true);
  }, 200);
}

function handleSearch(loading?: boolean, reset: boolean = true) {
  if (reset) {
    pagination.current = 1;
  }
  handleQuery(loading);
}

function onPageChange(page: number) {
  pagination.current = page;
  if (props.remote) {
    handleQuery();
  }
}

function onSortChange(page: any, filters: any, sorter: any, { action }: any) {
  if (action == "sort" && sorter.order) {
    emits("onSortChange", {
      sort: sorter.field,
      order: sorter.order == "ascend" ? "asc" : "desc",
    });
    // if (!props.isPagination) {
    //   changeSort(sorter.field, sorter.order == 'ascend' ? 'asc' : 'desc')
    // }
  }
}

function changeSort(field: string, order: string) {
  tableData.value = tableData.value.sort((a: any, b: any) => {
    if (order == "asc") {
      return a[field]?.localeCompare(b[field]);
    } else {
      return b[field]?.localeCompare(a[field]);
    }
  });
}

function onSizeChange(size: number) {
  pagination.current = 1;
  pagination.pageSize = size;
  if (props.remote) {
    handleQuery();
  }
}

onMounted(init);

defineExpose({
  handleSearch,
  handleReset,
  handleQuery,
});
</script>
